<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=0">
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache" content="no-cache">
    <link rel="icon" href="data:;base64,=">
    <title>Document</title>
    </head>
    <style>
    *{margin:0;padding:0;box-sizing:border-box;}
    html,body{position:absolute;width:100%;height:100%;min-width:1366px;min-height:768px;background: linear-gradient(skyblue,khaki);}
    /* 定义滚动条宽度 */::-webkit-scrollbar {width:4px;height:4px;}
    /*定义滚动条  轨道背景色+圆角*/::-webkit-scrollbar-track {border-radius: 2px;background-color: #555;}
    /*定义滚动条  滑块背景色+圆角*/::-webkit-scrollbar-thumb {border-radius: 2px;background-color: #C3C4C3;}
    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
    
    
    #app{
        position:absolute;
        width:900px;
        height:fit-content;
        left:5%;
        margin-top:40px;
        /* transform: translate(-50%,0); */
        padding:10px;
        background-color:#E1E0FC;
        border-radius:5px;
    }
    .bt{
       width:fit-content;
       height:fit-content;
       margin-bottom:20px;
       color:white;
       font-size:12px;
       padding:2px 6px;
       background-color:#7774F6;  
    }
    .bt:not(:nth-child(1)){
         margin-top:20px;
    }
    </style>
<body>
    
    <div id="app" >
          <div class="bt">行内属性</div>
          <div  id="dom1"  e-attr="title=title;className=className" e-evt="onclick=click('哈哈',v1?'a':'b');ondblclick=click2('haha',v1+v2)">
                e-attr="title=title;className=className"
          </div>   
          <div class="bt">文本内容(混合)</div>
          <div  id="dom2">
                张三来到商场看到  {{GetValue1( "张三 \"特殊\"" , v1 , v2 , v3?true:v4   ) + '测试1  '}} 的商品 => {{ value1 }} 尾部
          </div>  
          <div class="bt">文本内容(代码)</div>
          <div  id="dom3">
                '测试1  ' + value1  + value2 + "测试2 " +  GetValue1( "张三 \"特殊\"" , v1 , v2 , v3?true:v4  , GetValue2( v5,v6 ,'hhaha'+v7 ) ) +'测试3' + value3
          </div>
    </div>

</body>
</html>
<script>

let dom1=document.getElementById('dom1') , dom2=document.getElementById('dom2') , dom3=document.getElementById('dom3');

let attr1=dom1.getAttribute('e-attr').trim();
let attr2=dom1.getAttribute('e-evt').trim();
let txt1=dom2.innerText.trim();
let txt2=dom3.innerText.trim();
     console.log(attr1);
     console.log(attr2);
     console.log(txt1);
     console.log(txt2);

console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

let regFun=/^([A-z]|\_|\$)+\d*\s*\(.*\)$/;              // 以 字母_或$ 开头的 方法   
let regSM2=/(\+|\-|\*|\\|\?|\=|\(|\)|\%|\&|\[|\])+/;    // 匹配是否包含运算符
let regCs=/^([A-z]|\_|\$)+/;                            // 以字母 _ 和 $ 开头的 肯定是 参数名  (  排除掉 '"abc"'  这种 )



/**
 * 用户匹配  {{}}
 */   
const BD0=Object.create(null);
      BD0['{']=1,BD0['}']=2;

/**
 * 用于匹配字符串的边界
 * 
 * Boundaries used to match strings
 */    
 const BD1=Object.create(null);
       BD1["'"]=1,BD1['"']=2,BD1['`']=3;

/**
 * 用于匹配 各种运算符
 * 
 * Used to match commonly used operators
 * For example: +-*?/><=%:&()[]!
 */    
 var BD2=Object.create(null);
     BD2['+']=1,BD2['-']=1,BD2['*']=1,BD2['\\']=1,BD2['%']=1,BD2['?']=1,BD2['>']=1,BD2['<']=1,BD2['=']=1,BD2['&']=1,BD2[':']=1,BD2[',']=1,BD2['!']=1;
     BD2['(']=2,BD2[')']=1;     // 2  方法 () 
     BD2['[']=3,BD2[']']=4;     // 3  data [] 的方法



/** 用于存储 {{ }} 的开头和结尾索引 */
const BSN=[],BEN=[]        
/**
 *  对本内容中的数据进行 分割 并 处理 
 * 
 */ 
const BracketDataSplitting=(str)=>{
        BSN.length=0;
        BEN.length=0;
    let i=0,l=str.length-1,v='',n=0,f=0;
    let ss='{',se='}';
    let d=[],s=0,e=0;
    let out='';
        while(i<l){
              v=str[i];
              if( f===0 && v===ss ){
                   if( str[i+1]===ss && str[i+2]!==ss ){//匹配正确的开始边界 {{ 排除:  { 和 {{{ 这种
                      f=1 ;
                      e=i;
                   } 
                   i++;

              }else if( f===1 && v===se ){
                   
                   if(str[i+1]===se && str[i+2]!==se ){
                          f=0;
                          
                          if(e-s>1){
                              d.push(0,s,e);
                          }
                          s=i+2;
                          
                          d.push(1,e,i)
                   }

                   i++

              }
            i++;
        }

        if(l+1-s>0)d.push(0,s,l+1);   //尾部
        i=0,l=d.length;
        while(i<l){
            n=d[i],s=d[i+1],e=d[i+2];
            if(n===0){   // 普通文本 
                 console.log(str.slice(s,e))
                 out+='\"'+str.slice(s,e)+'\"'+(i!==l-3?' + ':'')
            }else{       // 待处理数据
                 console.log(str.slice(s+2,e))
                 out+='(' + TextCodeParsing( str.slice(s+2,e) )+ ' ) ' + (i!==l-3?' + ':'');
            }
            i+=3;
        }

        console.log(out);
        debugger

}
/**
 * 文本代码解析 
 * 
*/
const TextCodeParsing=(str)=>{
       str=str.trim();
   let u;    
   let i=0,l=str.length,s='',s2='',n=0,sn=0;
   let key='';
   let bj='',bs=0;;
   let f=0,f2=0;        //0 : 全匹配阶段 , 1: 匹配字符串边界中, 2:匹配运算符 , 3:匹配key
   let vrr=[];      // ... [ *0 , str ]  *0 => 0:字符串||运算符 , 1:key
   let vStr='';

       // f=> 0:普通状态, 1:字符串匹配 ,2: key匹配 ,3:符号匹配
       while(i<l){
            s=str[i];

            // 判断 字符串边界
            if(f===0||f===1){
                // 匹配 字符串中的 转义字符跳过到下一个  (注 如: \"" )   ,仅在字符串中匹配转义字符
                if(s==='\\'){
                    i+=2;
                    s=str[i];
                }
                n=BD1[s]||0;
                if(n>0){
                    f=1;         // 确定进入字符串边界匹配模式
                    if(bj===''){
                            // 起始边界, 以为排除了转义的情况, 因此字符串的边界标识符必然是相等的 
                            bj=s;
                            bs=i;
                    }else{
                            //结束判断
                            if(bj===s){
                                    bj=''; 
                                    f=0;  
                                    console.log(`匹配出的字符串 =>  ${str.slice(  bs , i+1 )} `)
                                   
                                    vStr += str.slice(  bs , i+1 );
                                    
                                    i++;
                                    continue;   // 跳至下一个
                            }
                    }
                }
            };
            
            // 判断运算符 
            if(f===0){
                    n=BD2[s]||0;
                    if(n>0){
                        key=key.trim();
                        if(key!==''){
                                console.log(` key => ${ key } `)
                                if(key==='v7')debugger;
                                // 判断这个key是否为一个 Function , 其后是否紧跟着一个 (
                                sn=i;
                                f2=0;
                                while(true){
                                    s2=str[sn];
                                    if(s2!==' '){
                                         if(s2!=='('){
                                             break;
                                         }else{
                                             f2=1;   // 这是一个Function
                                             break;   
                                         }
                                    }
                                    sn++;
                                }
                                //  !!!!!!!! 此处除了 function外, 还要 判断 key 的类型 和 特殊值的 key

                                vStr+=(f2===0?'$_':'$_MM_')+key;
                                key='';
                        };
                        vStr+=s;
                        sn=i;
                        //判断下一个是否也是运算符
                        while(true){
                                sn++;
                                s=str[sn];
                                if(s!==' '){
                                        n=BD2[s]||0;
                                        if(n>0){
                                            vStr+=s; 
                                        }else{
                                            i=sn;
                                            break
                                        }
                                }else{
                                        vStr+=s;
                                }
                        }

                        // 上面 i = sn , 接下来 优先 判断  不为 运算符的字符是否是 字符串边界 ,  
                        continue;
                    }
                    

            };
            
            // 既不属于 字符串 也不属于 运算符的部分 为 key 
            if(f===0)key+=s;

          i++;
       };
       key=key.trim();
       if(key!==''){
                console.log(`尾部 key => ${key}`)
                vStr+='$_'+key;
       };  
      console.log('~~~~~~~~~~~~~~~~~~~~')
       console.log(vStr)
    
       return vStr;

}




BracketDataSplitting(txt1)



// fun(txt2);




</script>